﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Net.Mail;
using System.ComponentModel;

namespace Common.Util
{
    /// <summary>
    /// 发送邮件的线程类
    /// </summary>
    public class MailSender
    {
        private static log4net.ILog _logger = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        private static MailSender _instance = null;
        private readonly object _locker = new object();
        private Thread _worker = null;
        Queue<MailReq> _itemQ = new Queue<MailReq>(); //保存任务的队列

        private MailSender()
        {
            _worker = new Thread(Consume);
            _worker.Start();
        }

        static public MailSender Instance()
        {
            if (_instance == null)
                _instance = new MailSender();

            return _instance;
        }

        /// <summary>
        /// 将待发送邮件内容放入队列
        /// </summary>
        public void EnqueueItem(string SMTP, bool SMTPAuth, string SMTPUser, string SMTPPassword, string id,
            MailAddress from, string[] to, string[] bcc, string title, bool htmlBody, string content)
        {
            MailReq item = new MailReq();
            item.SMTP = SMTP;
            item.SMTPAuth = SMTPAuth;
            item.SMTPUser = SMTPUser;
            item.SMTPPassword = SMTPPassword;
            item.id = id;
            item.from = from;
            item.to = to;
            item.bcc = bcc;
            item.title = title;
            item.htmlBody = htmlBody;
            item.content = content;

            lock (_locker)
            {
                _logger.Debug("EnqueueItem: Enquene mail, Id:" + id);

                _itemQ.Enqueue(item); 
                Monitor.Pulse(_locker); //通知等待队列中的线程
            }
        }

        private void Consume()
        {
            while (true)
            {
                MailReq item = null;
                lock (_locker)
                {
                    
                    while (_itemQ.Count == 0)
                        Monitor.Wait(_locker); //释放锁，并阻止当前线程，直到其他线程发送pulse信号。 

                    item = _itemQ.Dequeue(); 

                    if (item == null)   //退出的信号
                        return;
                    else   //发送邮件
                        SendMail(item);
                }
            }
        }

        private void SendMail(MailReq item)
        {
            try
            {
                //创建邮件内容
                MailMessage message = new MailMessage();
                message.Subject = item.title;
                message.IsBodyHtml = item.htmlBody;
                message.Body = item.content;
                message.From = item.from;

                if (item.to != null)
                {
                    foreach(string to in item.to)
                    message.To.Add(to);
                }

                if (item.bcc != null)
                {

                    foreach (string bcc in item.bcc)
                        message.Bcc.Add(bcc);                    
                }

                //连接SMTP服务器发送
                SmtpClient client = new SmtpClient(item.SMTP);
                client.UseDefaultCredentials = item.SMTPAuth;
                client.Credentials = new System.Net.NetworkCredential(item.SMTPUser, item.SMTPPassword);
                client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
                client.SendAsync(message, item.id); //异步发送

                _logger.Debug("SendMail: Process mail, Id: " + item.id);
            }
            catch (Exception e)
            {
                _logger.Error("SendMail: " + e);
            }
        }

        public static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
        {

            if (e.Cancelled)
            {
                _logger.Info("SendCompletedCallback: Cancelled mail, Id: " + e.UserState.ToString());
            }
            if (e.Error != null)
            {
                _logger.Error("SendCompletedCallback: Error mail, Id: " + e.UserState.ToString());
            }
            else
            {
                _logger.Debug("SendCompletedCallback: Sent mail success, Id: " + e.UserState.ToString());
            }
        }

        class MailReq
        {
            public string SMTP;         //SMTP地址
            public bool SMTPAuth;       //是否验证SMTP
            public string SMTPUser;     //SMTP用户名
            public string SMTPPassword; //STMP密码
            public string id;
            public MailAddress from;    //发行人地址
            public string[] to;         //收信人地址
            public string[] bcc;        //BCC地址
            public string title;        //邮件标题
            public bool htmlBody;       //是否是HTML邮件
            public string content;      //邮件内容
        }
    }
}
